using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class Controller : MonoBehaviour
{
    public static Controller Instance { get; private set; }
    // 鼠标左键是否按下
    private bool isMouseDown = false;

    private LineRenderer line;

    // 屏幕上的四个点，用于绘制矩形
    private Vector3 leftUpPoint;
    private Vector3 rightUpPoint;
    private Vector3 leftDownPoint;
    private Vector3 rightDownPoint;

    // 射线检测获取到的信息
    private RaycastHit hitInfo;
    public LayerMask groundMask;
    private Vector3 beginWorldPos;
    // 选择到的士兵对象 存储在该容器
    public List<SoldierObj> soldierObjs = new List<SoldierObj>();
    GameObject target;

    void Awake()
    {
        Instance = this;
    }

    void Start()
    {
        line = GetComponent<LineRenderer>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 鼠标开始按下位置
            leftUpPoint = Input.mousePosition;
            isMouseDown = true;

            // 通过射线检测 得到地面上的点 之后 用于 范围检测
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo, 1000, groundMask))
                beginWorldPos = hitInfo.point;

            SingleSelection();
        }
        else if (Input.GetMouseButtonUp(0))
        {
            isMouseDown = false;
            // 停止绘制，将线段的点数量设为 0
            line.positionCount = 0;

            // 框选择士兵逻辑处理
            BoxSelection();
        }

        DrawBox();

        //控制士兵移动
        ControlSoldiersMove();
    }

    void DrawBox()
    {
        // 处理线段绘制逻辑
        if (isMouseDown)
        {
            // 设置屏幕上的 4 个点的 z 坐标为 5
            leftUpPoint.z = 5;

            rightDownPoint = Input.mousePosition;
            rightDownPoint.z = 5;

            rightUpPoint.x = rightDownPoint.x;
            rightUpPoint.y = leftUpPoint.y;
            rightUpPoint.z = 5;

            leftDownPoint.x = leftUpPoint.x;
            leftDownPoint.y = rightDownPoint.y;
            leftDownPoint.z = 5;

            // 设置线段的点数为 4，并将点设置为世界坐标系下的位置
            line.positionCount = 4;
            line.SetPosition(0, Camera.main.ScreenToWorldPoint(leftUpPoint));
            line.SetPosition(1, Camera.main.ScreenToWorldPoint(rightUpPoint));
            line.SetPosition(2, Camera.main.ScreenToWorldPoint(rightDownPoint));
            line.SetPosition(3, Camera.main.ScreenToWorldPoint(leftDownPoint));
        }
    }

    /// <summary>
    /// 框选择士兵逻辑处理
    /// </summary>
    private void BoxSelection()
    {
        // 清空之前的选择
        for (int i = 0; i < soldierObjs.Count; i++)
            soldierObjs[i].SetSelSelf(false);
        soldierObjs.Clear();

        // 选择当前的对象
        // 通过射线检测 得到地面上的另一个点 用于 范围检测
        if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo, 1000, groundMask))
        {
            // 范围检测用的中心点 （由于 摄像机 朝向 是世界坐标系正方向 没有旋转 所以我们可以这样做）
            Vector3 center = new Vector3((hitInfo.point.x + beginWorldPos.x) / 2, 1, (hitInfo.point.z + beginWorldPos.z) / 2);

            // 范围检测 盒装的 长宽高的一半
            Vector3 halfExtents = new Vector3(Mathf.Abs(hitInfo.point.x - beginWorldPos.x) / 2, 1, Mathf.Abs(hitInfo.point.z - beginWorldPos.z) / 2);

            // 得到 这个盒装范围内的 所有碰撞器
            Collider[] colliders = Physics.OverlapBox(center, halfExtents);
            for (int i = 0; i < colliders.Length; i++)
            {
                SoldierObj obj = colliders[i].GetComponent<SoldierObj>();
                if (obj != null)
                {
                    obj.SetSelSelf(true);
                    soldierObjs.Add(obj);
                }
            }
        }
    }

    /// <summary>
    /// 单选
    /// </summary>
    private void SingleSelection()
    {
        // 通过射线检测
        if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo, 1000))
        {
            beginWorldPos = hitInfo.point;
            SoldierObj obj = hitInfo.transform.GetComponent<SoldierObj>();
            if (obj != null)
            {
                obj.SetSelSelf(true);
                soldierObjs.Add(obj);
            }
        }
    }

    private void ControlSoldiersMove()
    {
        if (Input.GetMouseButtonDown(1))
        {
            //没有士兵不移动
            if (soldierObjs.Count == 0)
                return;

            //获取目标点 通过射线检测
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo, 1000))
            {
                if (hitInfo.transform != null)
                {
                    if (hitInfo.transform.GetComponent<Buildable>()) return;
                    target = hitInfo.transform.gameObject;
                    MoveToDestination(hitInfo.point);
                }

            }
        }
    }

    /// <summary>
    /// 将选中的角色移动到目标点周围的圆周上
    /// </summary>
    public void MoveToDestination(Vector3 point)
    {
        // 计算每个角色在圆周上分配的角度间隔（将360度平均分配给所有角色）
        float angleStep = 360f / soldierObjs.Count;

        // 遍历所有选中的角色
        for (int i = 0; i < soldierObjs.Count; i++)
        {
            // 计算当前角色对应的角度（按顺序分配）
            float angle = i * angleStep;

            // 计算该角度在圆周上的具体位置坐标，圆周半径设置为角色的攻击距离
            Vector3 position = CalculatePositionOnCircle(angle, point, soldierObjs[i].attackDistance);

            // 设置角色的目标位置
            soldierObjs[i].Move(position, target);
        }
    }

    /// <summary>
    /// 根据给定角度计算圆周上的坐标位置
    /// </summary>
    /// <param name="angle">角度值（0-360度）</param>
    /// <param name="targetPosition">圆心位置</param>
    /// <param name="attackDistance">圆周半径</param>
    /// <returns>圆周上的三维坐标</returns>
    private Vector3 CalculatePositionOnCircle(float angle, Vector3 targetPosition, float radius)
    {
        // 将角度转换为弧度（Mathf.Cos/Sin需要使用弧度值）
        float radians = Mathf.Deg2Rad * angle;

        // 计算圆周上的X坐标：圆心X + 半径 * 角度的余弦值
        float x = targetPosition.x + radius * Mathf.Cos(radians);

        // 计算圆周上的Z坐标：圆心Z + 半径 * 角度的正弦值
        float z = targetPosition.z + radius * Mathf.Sin(radians);

        // 返回新坐标（Y轴保持与圆心相同的高度）
        return new Vector3(x, targetPosition.y, z);
    }
}
